package main

import (
	"fmt"
	"sync"
)

func main() {
	//LockRun()
	//TwiceLock()
	//channelRun()
	//finalChannelRun()
	//moreChannelRun()
	groupChannelRun()
}

//TODO 错误实例演示lock
func LockRun() {
	var mu sync.Mutex
	go func() {
		fmt.Println("hello")
		mu.Unlock()
	}()
	mu.Lock()
}

//TODO 错误实例演示双lock
func TwiceLock() {
	var mu sync.Mutex
	mu.Lock()
	go func() {
		fmt.Println("hello")
		mu.Unlock()
	}()
	mu.Lock()
}

//TODO 稍微正确实例，使用channel,需要注意channel缓冲区大小
func channelRun() {
	done := make(chan int)
	go func() {
		fmt.Println("hello")
		<-done //接收数据
	}()
	done <- 1 //发送数据
}

//TODO 正确实例，其它线程先发送，main线程接收
func finalChannelRun() {
	done := make(chan int, 1)
	go func() {
		fmt.Println("hello")
		done <- 1 //发送数据
	}()
	<-done //接收数据
}

//TODO 多线程等待，实例1
func moreChannelRun() {
	done := make(chan int, 10) //带10个缓存
	// 开N个后台打印线程
	for i := 0; i < cap(done); i++ {
		go func() {
			fmt.Println("hello")
			done <- 1
		}()
	}
	// 等待N个后台线程完成
	for i := 0; i < cap(done); i++ {
		<-done
	}
}

//TODO 多线程等待，实例2
func groupChannelRun() {
	var wg sync.WaitGroup
	// 开N个后台打印线程
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func() {
			fmt.Println("hello")
			wg.Done()
		}()
	}
	// 等待N个后台线程完成
	wg.Wait()
}
